package com.placedial;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Map.Entry;

public class ParseInput {

	/**
	 * @param args
	 */
	//error message
	public static final String INTERROR= " should be integer ";
	public static final String VERTEXERROR=" syntacs error: eg: V1, ";
	public static final String DUPLICATE=" is duplicate";
	public static final String KOUT="k is out of boundary";
	public static final String SOUT="graph size is not correct";
	public static final String VDERROR=" vertex did not define ";
	public static final String UNDIREC_ERROR="graph must to be underect";
	
	
	//file structure
	private HashMap<Integer, ArrayList> inputFile=new HashMap<Integer,ArrayList>(); //input file stucture : = [linenumber, [v1, v2 v3 ...]]
	private Set vSet=new HashSet();    // vertice set
	private int k;       //require number of vertex cover
	private int size;  //number of vertices
	private String error="";
	private String lineseperator=System.getProperty ("line.separator");
	
	//graph structure
	
	private HashMap<String,Set> graph=new HashMap<String,Set>();
	
	private Set coverSet=new HashSet();
	
	
	
	
	
	
	
	public void convertToGraph(String path) throws IOException{
		this.runTimecheck(path);
		if(error.equals("")){
			
			HashMap<Integer,ArrayList> mp=this.getInputFile();
			Set set=mp.entrySet();
			Iterator mpit=set.iterator();
			while(mpit.hasNext()){
				Entry<Integer,ArrayList> entry=(Entry<Integer, ArrayList>) mpit.next();
				ArrayList value=entry.getValue();
				int lineNo=entry.getKey();
				int arrayIndex=0;
				
				String vertexKey=(String) value.get(0);
				Set adjSet=new HashSet();
				for(int i=1;i<value.size();i++){
					adjSet.add(value.get(i));
					
					
				}
				
				this.graph.put(vertexKey, adjSet);
			}
			
			HashMap<String, Set> tempGraph=this.graph;
			Set gset=tempGraph.entrySet();
			Iterator gIt=gset.iterator();
			while(gIt.hasNext()){
				
				Entry<String,Set> gentry= (Entry<String, Set>) gIt.next();
				String gkey=gentry.getKey();
				Set gvalue=gentry.getValue();
				if(gvalue.size()!=0){
					for(Object v: gvalue){
						Set tempSet=tempGraph.get(v);
						if(!tempSet.contains(gkey)){
							this.error=error+UNDIREC_ERROR+", please check vertex "+gkey;
							return;
						}
					}
				}
				
				
			}
			
		}
		
		
	}
	
	public void runTimecheck(String path) throws IOException{
		
		this.processFile(path);
		if(k>size){
			error=error+KOUT+lineseperator;
		}
		if(vSet.size()!=size){
			error=error+SOUT+lineseperator;
		}
		
		
		HashMap<Integer,ArrayList> mp=this.getInputFile();
		Set set=mp.entrySet();
		Iterator mpit=set.iterator();
		while(mpit.hasNext()){
			Entry<Integer,ArrayList> entry=(Entry<Integer, ArrayList>) mpit.next();
			ArrayList value=entry.getValue();
			int lineNo=entry.getKey();
			for(Object v: value){
				String vertex=(String) v;
				if(!vSet.contains(vertex)){
					error=error+"line "+lineNo+": "+vertex+VDERROR+lineseperator;
				}
			}
		}
		
		
		
		
		
	}
	
	
	
	public void processFile(String path)throws IOException {
		FileReader fr = new FileReader(path);
	    BufferedReader br = new BufferedReader(fr);
	    String s;
	    int lineNo=1;
	    
	    ArrayList list;
	    while ((s = br.readLine()) != null) {
		    list=new ArrayList();
		    String line=s.trim();
		    if(!line.equals("")){
		    	StringTokenizer token;
		    	int tokenNo=0;
		    	
		    	switch(lineNo){
		    	
		    	case 1:
		    		try{
		    			k=Integer.parseInt(line);
		    			
					    lineNo++;
		    		}catch(Exception e){
		    			error=error+"line " +lineNo+": "+line+INTERROR+this.lineseperator;
		    			lineNo++;
		    			
		    		}
		    		break;
		    		
		    	case 2:
		    		try{
		    			this.size=Integer.parseInt(line);
		    			
					    lineNo++;
		    		}catch(Exception e){
		    			error=error+"line "+lineNo+": "+line+INTERROR+this.lineseperator;
		    			lineNo++;
		    			
		    		}
		    		break;	
		    	
		    	
		        default:
		        	
		        	token = new StringTokenizer(line);
		        	 while(token.hasMoreTokens()) {
		        	  
			            String vertex=token.nextToken();
			            int stLength=vertex.length();
			            if(tokenNo==0){
	                      if(vertex.endsWith(",")&&stLength>=2){
	           	            vertex=vertex.substring(0,stLength-1);
	           	            //check if vertex is duplicate
	           	            if(vSet.contains(vertex)){
	           	            	error=this.error+"line "+lineNo+": " +vertex+DUPLICATE+this.lineseperator;
	           	            	break;
	           	            }else{
	           	             list.add(vertex);
	           	             vSet.add(vertex);
	           	            }
	           	          }
	                      else{
	           		       this.error=error+"line "+lineNo+": " +vertex+VERTEXERROR+this.lineseperator;
	           		       break;
	           	          }
	                    }
			            else{
	           	          list.add(vertex);
			            }
			         
			            tokenNo++;
			        }
		           
		           inputFile.put(lineNo, list);
			       lineNo++;
		           break;
		            
		        }
		        
		    }
		    
		    
	    	
	    	
	    }
	    
	    
	    fr.close();
	}



	public HashMap<Integer, ArrayList> getInputFile() {
		return inputFile;
	}



	public void setInputFile(HashMap<Integer, ArrayList> inputFile) {
		this.inputFile = inputFile;
	}



	public int getK() {
		return k;
	}



	public void setK(int k) {
		this.k = k;
	}



	public int getSize() {
		return size;
	}



	public void setSize(int size) {
		this.size = size;
	}



	public Set getVSet() {
		return vSet;
	}



	public void setVSet(Set set) {
		vSet = set;
	}



	public String getError() {
		return error;
	}



	public void setError(String error) {
		this.error = error;
	}

	public HashMap<String, Set> getGraph() {
		return graph;
	}

	public void setGraph(HashMap<String, Set> graph) {
		this.graph = graph;
	}

	

	

	public Set getCoverSet() {
		return coverSet;
	}

	public void setCoverSet(Set coverSet) {
		this.coverSet = coverSet;
	}

	public String getLineseperator() {
		return lineseperator;
	}

	public void setLineseperator(String lineseperator) {
		this.lineseperator = lineseperator;
	}


	
	
	
}
